home *** CD-ROM | disk | FTP | other *** search
-
- Hi folks, this is Tran... This text explains START32, my 386 protected
- mode header... I'm assuming youre an assembler programmer. If you are not,
- this thing will do you no good. I'm also assuming you have some experience,
- and knowledge of the 386 wouldn't hurt either... If you don't know the 386,
- I suggest you get a good book if you really want to code it...
-
-
- First of all:
- -------------
- I coded START32 for myself, it is designed and optimized for my needs. The
- greatest of which is the need for speed... That is the reason I do not
- implement paging in this thing, too slow... Also, since the only real mode
- INTs I usually need are DOS file functions, the V86 handler is not perfect,
- but it does DOS and BIOS just fine.
-
-
- What it does:
- -------------
- START32 is a piece of code that handles most of the things associated with
- using and getting into and out of 32bit protected mode. It also allows your
- protected mode programs to access the regular real-mode DOS and BIOS functions.
- START32 will check mundane little things like the processor and memory, then
- if the system is 386+ and not already in protected mode, it will switch the
- system into 32bit protected mode. In protected mode the system will run in
- flat memory, that is you won't need to bother with segment registers, and
- large data arrays will be much easier to handle...
-
-
- How the system works:
- ---------------------
- After START32 initializes protected mode, it will jump to a label '_main',
- which mush be declared public in your code. This is the starting point of your
- program. All of the code and data in your program will reside in one large
- segment called 'code32' ... this is a 4gig segment. You do regular code using
- the 386 instruction set. To access a real-mode interrupt function, you load
- up 'virtual registers' with the values you want passed to the interrupt, then
- you load up AL with the number of the interrupt you wanna call, then you call
- INT 30h. The system will use the 386's v86 mode to call the real mode int.
- After which, the values in the 'virtual regs' will be what the interrupt
- handler passed back (All the real registers are preserved).
-
-
- Selectors:
- ----------
- Instead of physical segment pointers, in protected mode, the 386 uses
- selectors. Selectors are indexes into a table of data that describe the
- memory location the specific index points to. But you need not concern
- yourself with these tables (GDT, IDT, LDTs)... This thing takes care of them.
- All you need to know, is that there are 3 basic selectors available to you.
- 8, 10h, and 18h... 8 is the selector for the code segment, this is the 4gig
- segment which you put all your flat code into. 10h is the selector for the
- data segment, the memory is physically the same as the code segment, but
- it must be done this way. That is 8 and 10h point to the same large segment,
- but CS must use 8, and the data segregs must use 10h... 18h is a data
- selector that points to the beginning of memory. 8 and 10h both start at the
- beginning of the segment 'code32' in memory, wherever it may be. But 18h
- always starts at absolute physical adress 0000:0000... This is in case you
- want to access something that resides before the beginning of the 32bit code,
- like the BIOS data area or the PSP... Upon arrival at '_main', CS ofcourse is
- 8. DS, ES, FS, and SS are 10h. And GS is 18h. And you should keep them this
- way because START32, whose job is by far not done after it passes control to
- your code, expects it this way.
-
-
- IRQs:
- -----
- START32 handles IRQs for both the real system, and your protected mode code.
- By default, all the IRQ functions point to a piece of code in START32 which
- redirects them to their real-mode handler. You can set your own protected mode
- IRQ handlers, and control will pass DIRECTLY to them when they are called.
- There are four possible scenarios between the type of IRQ handler and the
- mode the IRQ was called in. The handling procedure can be the original real
- mode handler, or your own protected mode handler. And the IRQ can occur in
- protected mode, or when the system is servicing a V86 real mode INT. For
- this reason, your protected mode IRQ handler should make no assumption about
- the state of the system. That is, upon entry your handler, the only things
- you can be sure of, is CS=8, and SS=10h... You must set the other segregs
- manually if you wish to use them. Also, you must remember to terminate your
- IRQ routine with an 'IRETD' instead of an 'IRET'. If you wish to call the
- original real mode handler from your protected mode handler, simply call the
- real mode int associated with that IRQ from your handler.
-
- BTW: No real mode interrupt vektor table entries are modified by START32, all
- the IRQs go through the IDT.
-
- Also: START32 will mask off IRQ 0 and 1 when it first starts. The system timer
- and keyboard IRQs, because there is really no use for them untill you put
- them to use.
-
-
- Memory:
- -------
- Like I said, the whole system uses flat memory when you use START32. There
- are 2 types, low memory - below 640k, and high memory - above 1M... START32
- does some very basic 'memory management', if you could call it that. You
- can request blocks of a certain size, and START32 will either give ya a
- pointer to the block, or tell ya theres not enough of that type of memory.
- The blocks are allocated from the bottom up. You cannot free a memory below
- an area that you allocated later. You CAN free memory though, simply by
- decreasing the 'base of memory' pointer START32 uses to track the current
- base of usable memory. This pointer (along with a few others) is made available
- to your program. One good way of using this in a function, is along with any
- registers you PUSH, you also PUSH the pointer to the type of memory you
- wanna use. After the function is done and there is no more use for the memory
- it has allocated, you POP the pointer. If you need any memory area permanently
- throught the program, you should allocate it at the beginning, and ofcourse
- never decrease the pointer beyond this area.
-
-
- Crashes:
- --------
- One thing about coding protected mode, you do not have the use of a
- debugger in finding bugz... Youre gonna have to make due with your own traps
- and internal debug aids... But a crash in protected mode is not as bad as in
- real mode. START32 handles the 386 exceptions. If any type of exception
- occurs, START32 will stop the program, do a debug dump of the exception
- number, registers, and stack ... and quit to DOS... The system will very
- rarely lock up, and the DOS environment will hardly ever be screwed up...
- Some reasons are that like I said, no real mode interrupt vektors are
- modified, and any area below the beginning of your program is usually only
- accessible through GS. This means that when your code goes astray, it cant
- overwrite DOS of the int vect table, or any TSRs below it, or anything. And
- there is hardly ever anything that can be screwed up above a program. An
- exception will usually occur very soon after a screwup in your code. Two of
- the most common exceptions are:
-
- 6 - an invalid opcode. Either something overwrote your code, or you code
- jumped off into limbo...
- 0dh - a general protection violation. Many things can cause this.
-
-
- The system itself:
- ------------------
- First of all, START32 expects: CS=8, DS=ES=SS=FS=10h, GS=18h, and the
- direction flag cleared when you call any of its functions.
-
-
- In the included source code, at the top, the values are:
-
- LOWMIN - the minimum amount of free low memory (minus the code) that
- has to be present for START32 to allow the program to run.
-
- EXTMIN - the minimum amount of extended memory that has to be present
- for START32 to allow the program to run. (START32 will also quit
- if it finds less than 638k total low memory).
-
- TSTAK - the total stack space for START32 to give. The default value of
- 400h bytes is usually enough, unless you plan to do recursion.
-
- ISTAK - the amount of stack space to be given to a protected mode IRQ
- handler when an IRQ comes from V86 mode. (This also includes
- START32's exception handlers).
-
-
- START32 detects and will not run if a VGA is not present. This is not some
- system critical thing, but like I said, I wrote START32 for myself, and since
- I dont code anything that doesnt require a VGA right now, this is technically
- part of the system for me.
-
-
- START32 makes these variables available to your program:
-
- _totalextmem:word - The total amount of extended memory in the system (in K).
-
- _code16a:dword - Offset of the beginning of the program from absolute 0.
- This starts 100h bytes above the PSP.
-
- _code32a:dword - Offset of the beginning of protected mode code from
- absolute 0. This is useful for creating realative pointers
- to physical locations. That is if you wanted a pointer to
- the beginning of the VGA grafix area, realative to DS,
- move 0A0000h into a reg, then subtract _code32a from it.
- theres a macro provided to create such pointers, @rlp.
-
- _hextbl:bytes - Simply '0123456789ABCDEF'. It is used during an exception
- dump, but since it's there, might as well make it public
- since its so useful in printing hex numbers.
-
- _lomembase:dword - Current base of low memory (as a realative pointer, like
- all the other regular pointers in your code)... this is
- the beginning of free low memory that has not been
- allocated.
-
- _lomemtop:dword - Top of low memory as a realative pointer.
-
- _himembase:dword - Base of high memory, just like _lomembase.
-
- _himemtop:dword - Guess...
-
-
- v86r_ax, v86r_bx, v86r_cx, v86r_dx, v86r_si, v86r_di, v86r_bp, v86r_ds,
- v86r_es, v86r_ah, v86r_al, v86r_bh, v86r_bl, v86r_ch, v86r_cl, v86r_dh,
- v86r_dl, v86r_flags
-
- These are the 'virtual registers' you use to communicate with real-mode
- ints... v86r_flags though is used only to pass BACK flags, flags are not
- set to it before invoking the V86 int...
-
-
- Here are some 'functions':
-
- ------------------------------------------------------------------------------
- _exit - Exit to real mode.
-
- ------------------------------------------------------------------------------
- _ret - Simply points to a RET instruction.
-
- ------------------------------------------------------------------------------
- _getvect - Get interrupt vektor, vektors 0-1fh and 30h are reserved, 31h+
- dont exist, but 20h-2fh are IRQ's 0-0fh.
- In:
- BL - interrupt number
- Out:
- EAX - 32 bit offset in code
-
- ------------------------------------------------------------------------------
- _setvect - Set interrupt vektor.
- In:
- BL - interrupt number
- EAX - 32 bit offset in code
-
- ------------------------------------------------------------------------------
- _getlomem - Get a low memory block.
- In:
- EAX - size requested
- Out:
- CF=1 - not enough mem (carry flag set)
- EAX - ?
- CF=0 - memory allocated (carry flag clear)
- EAX - linear pointer to mem
-
- ------------------------------------------------------------------------------
- _gethimem - Get a high memory block.
- In:
- EAX - size requested
- Out:
- CF=1 - not enough mem
- EAX - ?
- CF=0 - memory allocated
- EAX - linear pointer to mem
-
- ------------------------------------------------------------------------------
- _getmem - Allocate any mem (first cheks low, then high).
- In:
- EAX - size requested
- Out:
- CF=1 - not enough mem
- EAX - ?
- CF=0 - memory allocated
- EAX - linear pointer to mem
-
- ------------------------------------------------------------------------------
- _lomemsize - Get amount of low mem free.
- Out:
- EAX - number of bytes free
-
- ------------------------------------------------------------------------------
- _himemsize - Get amount of high mem free.
- Out:
- EAX - number of bytes free
-
- ------------------------------------------------------------------------------
- _putdosmsg - Put a '$' terminated DOS string.
- In:
- EDX -> message (MUST be in low mem).
-
-
- How to use it:
- --------------
- It's very simple, you compile START32. Compile with multiple passes to
- resolve forward references. Then you link it with your other 32bit modules.
- START32 must be the first program in the link list. Try compiling and linking
- the example programs, then run them to make sure it runs on your system. The
- thing will just color the screen and pop up some numbers, press ESC to return
- to DOS.
-
-
- Some quickie tips on the 386 instruction set:
- ---------------------------------------------
- (This isn't anything new to those of you already familiar with it)
-
- First the extended registers: EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP,EIP
- are all 32bit registers. (No you can't access EIP directly)...
-
- The bit shift instructions, SHL, SHR, RCL, ect... accept immediate values
- greater than 1 now. This means 'SHL AX,5' is legal.
-
- The addressing mode has been extended. You can use a combination of ANY 2 of
- the 8 general purpose instructions and an immediate value in addressing. Also
- one of the registers can be multiplied by 2,4, or 8 right in the address field
- of the instruction youre using. So 'MOV BX,[EAX+ECX*4+78]' is legal.
- BTW: This is really good because it allows you to use the 'LEA' instruction
- to perform quick multiplies. Example: 'LEA EAX,[EAX*4+EAX]' is EAX=EAX*5.
-
- A version of the 'IMUL' instruction doesn't require preloading registers other
- than the one(s) you wanna multiply... examples:
- IMUL EAX,71 ; EAX=EAX*71
- IMUL EAX,ECX,33 ; EAX=ECX*33
-
- You can 'PUSH' immediates... 'PUSH 17983'
-
- I don't feel like explaining the double shift SHLD/SHRD instructions or any
- of the BT instructions, so if you don't know em, get a book...
-
-
-
- ------------------------------------------------------------------------------
- Anyways, play with this thing. If you like the flat memory and stuff then
- youre free to use this thing in whatever code you do, PD, shareware,
- commercial, or whatever...
-
- Any questions or anything, you can contact me on the
- Sound Barrier BBS (718)979-6629.
-
- L8r...
-
-